<template>
  <div class="demand-forecast-chat">
    <Layout style="height: calc(100vh - 120px)">
      <LayoutContent :style="contentStyle">
        <div class="chat-container">
          <div ref="messagesContainer" class="messages-container">
            <div 
              v-for="(message, index) in messages" 
              :key="index" 
              :class="['message-item', message.role]"
            >
              <div class="message-avatar">
                <span v-if="message.role === 'user'">{{ UserIcon }}</span>
                <span v-else>{{ RobotIcon }}</span>
              </div>
              <div class="message-content">
                <div class="message-text" v-html="formatMessage(message.content)"></div>
                <div class="message-time">{{ formatTime(message.time) }}</div>
              </div>
            </div>
            <div v-if="loading" class="message-item assistant">
              <div class="message-avatar">
                <span>{{ RobotIcon }}</span>
              </div>
              <div class="message-content">
                <div class="message-text">
                  <Spin size="small" />
                  <span style="margin-left: 8px;">正在思考中...</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </LayoutContent>
      <LayoutFooter :style="footerStyle">
        <div class="input-container flex-row-center">
          <Input
            v-model:value="inputMessage"
            placeholder="请输入您的问题..."
            :disabled="loading"
            @pressEnter="handleSend"
            style="flex: 1; min-width: 120px; margin-right: 8px;"
          />
          <Button 
            type="primary" 
            @click="handleSend"
            :loading="loading"
            :disabled="!inputMessage.trim()"
            style="margin-right: 8px;"
          >
            发送
          </Button>
          <Button 
            @click="handleStop"
            :disabled="!loading"
            style="margin-right: 8px;"
          >
            停止响应
          </Button>
          <Button
            type="default"
            @click="handleNewConversation"
            :disabled="loading"
            style="margin-left:auto;"
          >
            开启新对话
          </Button>
        </div>
      </LayoutFooter>
    </Layout>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import {
  Layout,
  LayoutContent,
  LayoutFooter,
  Input,
  Button,
  Spin,
  message,
} from 'ant-design-vue';
const UserIcon = '👤';
const RobotIcon = '🤖';
import { monthPurchasePlanChat } from '#/api/operate/monthPurchasePlan';

const contentStyle = {
  background: '#f0f2f5',
  padding: '24px',
  overflow: 'auto',
};
const footerStyle = {
  background: '#fff',
  padding: '16px 24px',
  borderTop: '1px solid #e8e8e8',
};

interface Message {
  role: 'user' | 'assistant';
  content: string;
  time: Date;
}
const messages = ref<Message[]>([]);
const inputMessage = ref('');
const loading = ref(false);
const conversationId = ref('');
const messagesContainer = ref<HTMLDivElement | null>(null);
const typingTimer = ref<NodeJS.Timeout | null>(null);
const fullAnswerBuffer = ref<{ index: number; text: string } | null>(null);

const handleSend = async () => {
  if (!inputMessage.value.trim() || loading.value) return;
  const userMessage = inputMessage.value.trim();
  // 立即清空输入框
  inputMessage.value = '';
  // 使用 nextTick 确保响应式更新立即生效
  await nextTick();
  messages.value.push({ role: 'user', content: userMessage, time: new Date() });
  scrollToBottom();
  const aiMessageIndex = messages.value.length;
  messages.value.push({ role: 'assistant', content: '', time: new Date() });
  loading.value = true;
  try {
    const result = await monthPurchasePlanChat({
      query: userMessage,
      conversation_id: conversationId.value || undefined,
      user: 'user',
      onMessage: (fullMessage: string) => {
        fullAnswerBuffer.value = { index: aiMessageIndex, text: fullMessage };
        if (typingTimer.value) { clearInterval(typingTimer.value as any); typingTimer.value = null; }
        startTypingEffect(aiMessageIndex, fullMessage);
      },
      onError: (error: Error) => {
        console.error('Chat error:', error);
        message.error('发送消息失败: ' + error.message);
        loading.value = false;
        // 发生错误时也要清理定时器
        if (typingTimer.value) {
          clearInterval(typingTimer.value as any);
          typingTimer.value = null;
        }
      },
      onComplete: () => {
        // 流完成时，只设置loading为false，让打字效果继续完成
        console.log('流式响应完成');
        loading.value = false;
        // 不立即清理typingTimer，让打字效果继续显示
        // typingTimer会在startTypingEffect中自然完成时自动清理
      },
    });
    if (result && result.conversation_id && !conversationId.value) conversationId.value = result.conversation_id;
    if (result && result.answer && messages.value[aiMessageIndex]) {
      if (!messages.value[aiMessageIndex].content) messages.value[aiMessageIndex].content = result.answer;
    }
    if (messages.value[aiMessageIndex]) {
      messages.value[aiMessageIndex].time = new Date();
      if (!messages.value[aiMessageIndex].content) message.warning('未收到回复，请检查Dify服务或查看控制台日志');
    }

    // 流结束时，确保停止打字效果并显示完整内容
    if (typingTimer.value) {
      clearInterval(typingTimer.value as any);
      typingTimer.value = null;
    }
    // 确保消息内容已完整显示
    if (fullAnswerBuffer.value && messages.value[aiMessageIndex]) {
      messages.value[aiMessageIndex].content = fullAnswerBuffer.value.text;
    } else if (result && result.answer && messages.value[aiMessageIndex]) {
      messages.value[aiMessageIndex].content = result.answer;
    }
  } catch (error) {
    console.error('Send message error:', error);
    message.error('发送消息失败，请重试');
    messages.value.pop();
    // 发生错误时也要清理定时器
    if (typingTimer.value) {
      clearInterval(typingTimer.value as any);
      typingTimer.value = null;
    }
  } finally {
    loading.value = false;
    // 确保打字效果已停止
    if (typingTimer.value) {
      clearInterval(typingTimer.value as any);
      typingTimer.value = null;
    }
    // 确保输入框已清空
    if (inputMessage.value) {
      inputMessage.value = '';
    }
    scrollToBottom();
  }
};
const handleClear = () => {
  if (typingTimer.value) { clearInterval(typingTimer.value as any); typingTimer.value = null; }
  messages.value = [];
  conversationId.value = '';
  inputMessage.value = '';
  fullAnswerBuffer.value = null;
};
const handleStop = () => {
  if (typingTimer.value) {
    clearInterval(typingTimer.value as any);
    typingTimer.value = null;
  }
  loading.value = false;
};
const handleNewConversation = () => {
  if (typingTimer.value) {
    clearInterval(typingTimer.value as any);
    typingTimer.value = null;
  }
  messages.value = [];
  conversationId.value = '';
  inputMessage.value = '';
  fullAnswerBuffer.value = null;
  messages.value.push({
    role: 'assistant',
    content: '您好！我是月维度采购计划助手，可以帮您分析采购与计划相关问题。请告诉我您的问题。',
    time: new Date(),
  });
};
const startTypingEffect = (messageIndex: number, fullText: string) => {
  if (typingTimer.value) clearInterval(typingTimer.value as any);
  if (!messages.value[messageIndex]) return;
  let currentLength = messages.value[messageIndex].content.length;
  const targetLength = fullText.length;
  if (targetLength <= currentLength) {
    messages.value[messageIndex].content = fullText;
    nextTick(() => scrollToBottom());
    return;
  }
  const speed = 30;
  typingTimer.value = setInterval(() => {
    if (!messages.value[messageIndex]) {
      if (typingTimer.value) { clearInterval(typingTimer.value as any); typingTimer.value = null; }
      return;
    }
    const latestFullText = fullAnswerBuffer.value?.text || fullText;
    if (currentLength >= latestFullText.length) {
      if (typingTimer.value) { clearInterval(typingTimer.value as any); typingTimer.value = null; }
      messages.value[messageIndex].content = latestFullText;
      // 打字效果完成时，确保loading为false
      loading.value = false;
      nextTick(() => scrollToBottom());
      return;
    }
    const charsPerUpdate = 2;
    const nextLength = Math.min(currentLength + charsPerUpdate, latestFullText.length);
    messages.value[messageIndex].content = latestFullText.substring(0, nextLength);
    currentLength = nextLength;
    nextTick(() => scrollToBottom());
  }, speed);
};
const scrollToBottom = () => {
  nextTick(() => {
    if (messagesContainer.value) {
      messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight;
    }
  });
};
const formatMessage = (content: string): string => {
  if (!content) return '';
  let formatted = content
    .replace(/\n/g, '<br>')
    .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
    .replace(/\*(.+?)\*/g, '<em>$1</em>')
    .replace(/`(.+?)`/g, '<code>$1</code>');
  return formatted;
};
const formatTime = (date: Date | undefined): string => {
  if (!date) return '';
  const d = new Date(date);
  return d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
};
onMounted(() => {
  messages.value.push({
    role: 'assistant',
    content: '您好！我是月维度采购计划助手，可以帮您分析采购与计划相关问题。请告诉我您的问题。',
    time: new Date(),
  });
});
onUnmounted(() => {
  if (typingTimer.value) { clearInterval(typingTimer.value as any); typingTimer.value = null; }
});
</script>

<style scoped>
.demand-forecast-chat { height: 100%; }
.chat-container { height: 100%; background: #fff; border-radius: 8px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; }
.messages-container { flex: 1; overflow-y: auto; padding: 24px; min-height: 400px; }
.message-item { display: flex; margin-bottom: 24px; animation: fadeIn 0.3s; }
.message-item.user { justify-content: flex-end; }
.message-item.assistant { justify-content: flex-start; }
.message-avatar { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; margin: 0 12px; }
.message-item.user .message-avatar { background: #1890ff; color: #fff; order: 2; }
.message-item.assistant .message-avatar { background: #f0f0f0; color: #666; }
.message-content { max-width: 70%; display: flex; flex-direction: column; }
.message-item.user .message-content { align-items: flex-end; }
.message-item.assistant .message-content { align-items: flex-start; }
.message-text { padding: 12px 16px; border-radius: 12px; line-height: 1.6; word-wrap: break-word; }
.message-item.user .message-text { background: #1890ff; color: #fff; border-bottom-right-radius: 4px; }
.message-item.assistant .message-text { background: #f0f0f0; color: #333; border-bottom-left-radius: 4px; }
.message-time { font-size: 12px; color: #999; margin-top: 4px; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.flex-row-center {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  width: 100%;
}
</style>


